// import com.alibaba.druid.DbType;
// import com.alibaba.druid.sql.SQLUtils;
// import com.alibaba.druid.sql.ast.SQLExpr;
// import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;
// import com.alibaba.druid.support.json.JSONUtils;
// import com.alibaba.druid.util.FnvHash;

// import java.util.ArrayList;
// import java.util.HashMap;
// import java.util.std::list;
// import java.util.std::map;
#pragma once

#include <string>
#include <map>
#include <list>

#include "../utils/FnvHash.h"
#include "../sql/ast/Object.h"
#include "../sql/SQLUtils.h"

class TableStat_Relationship;
class TableStat_Name;
class TableStat_Condition;
class TableStat_Column;

class TableStat_Mode : virtual public Object
{
public:
  static TableStat_Mode_ptr Insert;      //
  static TableStat_Mode_ptr Update;      //
  static TableStat_Mode_ptr Delete;      //
  static TableStat_Mode_ptr Select;      //
  static TableStat_Mode_ptr Merge;       //
  static TableStat_Mode_ptr Truncate;    //
  static TableStat_Mode_ptr Alter;       //
  static TableStat_Mode_ptr Drop;        //
  static TableStat_Mode_ptr DropIndex;   //
  static TableStat_Mode_ptr CreateIndex; //
  static TableStat_Mode_ptr Replace;
  static TableStat_Mode_ptr DESC; //

  int mark;

  TableStat_Mode(int mark);
  bool operator==(const TableStat_Mode_ptr ps) const;
};

class TableStat_Name : virtual public Object
{
public:
  string_ptr name;
  long hashCode64_;

  TableStat_Name(string_ptr name);

  TableStat_Name(string_ptr name, long hashCode64_);

  string_ptr getName();

  int hashCode();

  long hashCode64();

  bool equals(Object_ptr o);

  string_ptr toString();
  friend bool operator<(const TableStat_Name &ls,const TableStat_Name &rs) 
  {
    // return name->c_str() < c.name->c_str();
    std::string ls_n = ls.name->c_str();
    return ls_n.compare(rs.name->c_str());
  }
  // friend bool operator<(const TableStat_Name &rs) 
  // {
  //   // return name->c_str() < c.name->c_str();
  //   std::string ls_n = name->c_str();
  //   return ls_n.compare(rs.name->c_str());
  // }
};

class TableStat_Relationship : virtual public Object
{
public:
  std::shared_ptr<TableStat_Column> left;
  std::shared_ptr<TableStat_Column> right;
  string_ptr operator_;

  TableStat_Relationship(std::shared_ptr<TableStat_Column> left, std::shared_ptr<TableStat_Column> right, string_ptr operator_);

  std::shared_ptr<TableStat_Column> getLeft();

  std::shared_ptr<TableStat_Column> getRight();

  string_ptr getOperator();

  int hashCode();

  bool equals(Object_ptr obj);

  string_ptr toString();
  virtual string_ptr getClass();
};

class TableStat_Condition : virtual public Object
{
public:
  std::shared_ptr<TableStat_Column> column;
  string_ptr operator_;
  Object_list_ptr values;

  TableStat_Condition(std::shared_ptr<TableStat_Column> column, string_ptr xoperator);

  std::shared_ptr<TableStat_Column> getColumn();

  string_ptr getOperator();

  Object_list_ptr getValues();

  void addValue(Object_ptr value);

  int hashCode();

  bool equals(Object_ptr obj);

  string_ptr toString();
};

class TableStat_Column : virtual public Object
{
public:
  string_ptr table;
  string_ptr name;
  long hashCode64_;

  bool where;
  bool select;
  bool groupBy;
  bool having;
  bool join;
  bool primaryKey; // for ddl
  bool unique;     //
  bool update;
  std::shared_ptr<std::map<std::string, Object_ptr>> attributes;
  string_ptr fullName;

  /**
   * @since 1.0.20
   */
  string_ptr dataType;

  TableStat_Column(string_ptr table, string_ptr name);

  TableStat_Column(string_ptr table, string_ptr name, DbType_ptr dbType);

  TableStat_Column(string_ptr table, string_ptr name, long hashCode64_);

  string_ptr getTable();

  string_ptr getFullName();

  long hashCode64();

  bool isWhere();

  void setWhere(bool where);

  bool isSelect();

  void setSelec(bool select);

  bool isGroupBy();

  void setGroupBy(bool groupBy);

  bool isHaving();

  bool isJoin();

  void setJoin(bool join);

  void setHaving(bool having);

  bool isPrimaryKey();

  void setPrimaryKey(bool primaryKey);

  bool isUnique();

  void setUnique(bool unique);

  bool isUpdate();

  void setUpdate(bool update);

  string_ptr getName();

  /**
   * @since 1.0.20
   */
  string_ptr getDataType();

  /**
   * @since 1.0.20
   */
  void setDataType(string_ptr dataType);

  std::shared_ptr<std::map<std::string, Object_ptr>> getAttributes();

  void setAttributes(std::shared_ptr<std::map<std::string, Object_ptr>> attributes);

  int hashCode();

  string_ptr toString();

  bool equals(Object_ptr obj);

  // ATTRIBUTES(SQLOrderingSpecification_ptr, KEY, VALUE, STATUS);
};

class TableStat
{
public:
  int selectCount;
  int updateCount;
  int deleteCount;
  int insertCount;
  int dropCount;
  int mergeCount;
  int createCount;
  int alterCount;
  int createIndexCount;
  int dropIndexCount;
  int referencedCount;
  int addCount;          // odps add table
  int addPartitionCount; // odps add partition
  int analyzeCount;      // odps analyze table

  TableStat();

  int getReferencedCount();

  void incrementReferencedCount();

  int getDropIndexCount();

  void incrementDropIndexCount();

  void incrementAddCount();

  int getAddCount();

  void incrementAddPartitionCount();

  int getAddPartitionCount();

  int getCreateIndexCount();

  void incrementCreateIndexCount();

  int getAlterCount();

  void incrementAlterCount();

  int getCreateCount();

  void incrementCreateCount();

  int getMergeCount();

  void incrementMergeCount();

  int getDropCount();

  void incrementDropCount();

  void setDropCount(int dropCount);

  int getSelectCount();

  void incrementSelectCount();

  void setSelectCount(int selectCount);

  int getUpdateCount();

  void incrementUpdateCount();

  void setUpdateCount(int updateCount);

  int getDeleteCount();

  void incrementDeleteCount();

  void setDeleteCount(int deleteCount);

  void incrementInsertCount();

  int getInsertCount();

  void setInsertCount(int insertCount);

  int getAnalyzeCount();

  void incrementAnalyzeCount();

  string_ptr toString();
};
